{
 "cells": [
  {
   "metadata": {},
   "cell_type": "markdown",
   "source": "# 1 将图像，带噪音图像，以及噪音图像通过Sobel算子、Scharr算子、Laplacian算子和Canny算子处理后的图像整合到一张图上比较。",
   "id": "bf2501093288ea6b"
  },
  {
   "metadata": {
    "ExecuteTime": {
     "end_time": "2025-10-29T12:27:50.766032Z",
     "start_time": "2025-10-29T12:27:29.908315Z"
    }
   },
   "cell_type": "code",
   "source": [
    "import cv2 as cv\n",
    "import numpy as np\n",
    "\n",
    "#读取图片\n",
    "image = cv.imread('./image/mm.png')\n",
    "\n",
    "# 生成带噪声图像\n",
    "mean = 0  # 噪声均值\n",
    "sigma = 25  # 噪声强度（可调整）\n",
    "noise = np.random.normal(mean, sigma, image.shape).astype(np.int16)\n",
    "noisy_image = np.clip(image + noise, 0, 255).astype(np.uint8)\n",
    "\n",
    "#定义共享参数\n",
    "shared_params = {\n",
    "    \"org\": (10, 30),\n",
    "    \"fontFace\": cv.FONT_HERSHEY_SIMPLEX,\n",
    "    \"fontScale\": 1,\n",
    "    \"thickness\": 2,\n",
    "    \"color\": (0, 255, 0),\n",
    "    \"lineType\": cv.LINE_AA,\n",
    "}\n",
    "\n",
    "#原图\n",
    "original_image = cv.putText(image.copy(), \"Original Image\", **shared_params)\n",
    "# 带噪声图\n",
    "noisy_labeled = cv.putText(noisy_image.copy(), \"Noisy Image\", **shared_params)\n",
    "\n",
    "#Sobel算子\n",
    "sobel_x = cv.Sobel(noisy_image, cv.CV_64F, 1, 0, ksize=3)\n",
    "sobel_y = cv.Sobel(noisy_image, cv.CV_64F, 0, 1, ksize=3)\n",
    "sobel_result = cv.convertScaleAbs(sobel_x + sobel_y)\n",
    "# 转为BGR（方便统一拼接）+ 添加标签\n",
    "sobel_gray = cv.cvtColor(sobel_result, cv.COLOR_BGR2GRAY)  # 先转单通道灰度\n",
    "sobel_bgr = cv.cvtColor(sobel_gray, cv.COLOR_GRAY2BGR)  # 再转3通道BGR\n",
    "sobel_labeled = cv.putText(sobel_bgr, \"Sobel (X+Y)\", **shared_params)\n",
    "\n",
    "#Scharr算子\n",
    "scharr_x = cv.Scharr(noisy_image, cv.CV_64F, 1, 0)\n",
    "scharr_y = cv.Scharr(noisy_image, cv.CV_64F, 0, 1)\n",
    "scharr_result = cv.convertScaleAbs(scharr_x + scharr_y)\n",
    "# 转为BGR + 添加标签\n",
    "scharr_gray = cv.cvtColor(scharr_result, cv.COLOR_BGR2GRAY)\n",
    "scharr_bgr = cv.cvtColor(scharr_gray, cv.COLOR_GRAY2BGR)\n",
    "scharr_labeled = cv.putText(scharr_bgr, \"Scharr (X+Y)\", **shared_params)\n",
    "\n",
    "#Laplacian算子\n",
    "laplacian = cv.Laplacian(noisy_image, cv.CV_64F)\n",
    "laplacian_result = cv.convertScaleAbs(laplacian)\n",
    "# 转为BGR + 添加标签\n",
    "laplacian_gray = cv.cvtColor(laplacian_result, cv.COLOR_BGR2GRAY)\n",
    "laplacian_bgr = cv.cvtColor(laplacian_gray, cv.COLOR_GRAY2BGR)\n",
    "laplacian_labeled = cv.putText(laplacian_bgr, \"Laplacian\", **shared_params)\n",
    "\n",
    "#Canny算子\n",
    "canny_result = cv.Canny(noisy_image, 100, 150)  # 低阈值100，高阈值150\n",
    "# 转为BGR + 添加标签\n",
    "canny_bgr = cv.cvtColor(canny_result, cv.COLOR_GRAY2BGR)\n",
    "canny_labeled = cv.putText(canny_bgr, \"Canny (100,150)\", **shared_params)\n",
    "\n",
    "#整合所有图像\n",
    "# 第1行：原图、带噪声图、Sobel结果\n",
    "row1 = cv.hconcat([original_image, noisy_labeled, sobel_labeled])\n",
    "# 第2行：Scharr结果、Laplacian结果、Canny结果\n",
    "row2 = cv.hconcat([scharr_labeled, laplacian_labeled, canny_labeled])\n",
    "# 垂直拼接两行\n",
    "combined_image = cv.vconcat([row1, row2])\n",
    "\n",
    "#显示结果\n",
    "cv.imshow(\"Edge Detection Comparison (Noisy Image)\", combined_image)\n",
    "cv.waitKey(0)\n",
    "cv.destroyAllWindows()"
   ],
   "id": "d7e49a1d8bf2429f",
   "outputs": [],
   "execution_count": 5
  },
  {
   "metadata": {},
   "cell_type": "markdown",
   "source": "# 2.将图像及经过腐蚀，膨胀，开运算、闭运算，礼帽运算，黑帽运算，粗化、细化运算后的图像整合到一张图上做比较。",
   "id": "1d04b20fabc9cb4a"
  },
  {
   "metadata": {
    "ExecuteTime": {
     "end_time": "2025-10-29T12:38:18.957157Z",
     "start_time": "2025-10-29T12:38:16.292219Z"
    }
   },
   "cell_type": "code",
   "source": [
    "import cv2 as cv\n",
    "import numpy as np\n",
    "\n",
    "image = cv.imread('./image/mm.png')\n",
    "\n",
    "rect_kernel = cv.getStructuringElement(cv.MORPH_RECT, (5, 5))\n",
    "dialated_image = cv.dilate(image, rect_kernel, iterations=1)\n",
    "#cv.imwrite(\"dialated_image.png\", dialated_image)\n",
    "\n",
    "def draw_connected_image(src_img):\n",
    "    gray_img = cv.cvtColor(src_img, cv.COLOR_BGR2GRAY)\n",
    "    threshold_value = 20\n",
    "    _, binary_img = cv.threshold(gray_img, threshold_value, 255, cv.THRESH_BINARY)\n",
    "    _, labels, stats, centroids = cv.connectedComponentsWithStats(binary_img)\n",
    "    num_labels = len(stats) - 1\n",
    "    for i in range(1, num_labels + 1):\n",
    "        x,y,w,h,_ = stats[i]\n",
    "        cv.rectangle(src_img, (x, y), (x+w, y+h), (0, 255, 0), 2)\n",
    "\n",
    "    return src_img\n",
    "\n",
    "white = {\n",
    "    \"org\": (10,30),\n",
    "    \"fontFace\": cv.FONT_HERSHEY_SIMPLEX,\n",
    "    \"fontScale\": 1,\n",
    "    \"thickness\": 2,\n",
    "    \"color\": (255,255,255),\n",
    "    \"lineType\": cv.LINE_AA\n",
    "}\n",
    "\n",
    "black = white.copy()\n",
    "black[\"color\"] = 0\n",
    "black[\"thickness\"] = 10\n",
    "\n",
    "img_txt = cv.putText(image.copy(), \"Original Image\", **black)\n",
    "img_txt = cv.putText(img_txt, \"Original Image\", **white)\n",
    "detailed_img_txt = cv.putText(dialated_image.copy(), \"Dialated Image\", **black)\n",
    "detailed_img_txt = cv.putText(detailed_img_txt.copy(), \"Dialated Image\", **white)\n",
    "\n",
    "cv.imshow('dialated_image', cv.vconcat([\n",
    "    cv.hconcat([img_txt, draw_connected_image(image.copy())]),\n",
    "    np.zeros((10, image.shape[1] * 2, 3), dtype=np.uint8) + 255,\n",
    "    cv.hconcat([detailed_img_txt, draw_connected_image(dialated_image.copy())])\n",
    "]))\n",
    "\n",
    "cv.waitKey(0)\n",
    "cv.destroyAllWindows()"
   ],
   "id": "4dce8c6fbf559fca",
   "outputs": [],
   "execution_count": 9
  },
  {
   "metadata": {
    "ExecuteTime": {
     "end_time": "2025-10-29T12:38:11.446155Z",
     "start_time": "2025-10-29T12:38:07.587415Z"
    }
   },
   "cell_type": "code",
   "source": [
    "rect_kernel = cv.getStructuringElement(cv.MORPH_RECT, (5, 5))\n",
    "eroded_image = cv.erode(image, rect_kernel, iterations=1)\n",
    "\n",
    "def draw_connected_image(src_img):\n",
    "    gray_img = cv.cvtColor(src_img, cv.COLOR_BGR2GRAY)\n",
    "    threshold_value = 20\n",
    "    _, binary_image = cv.threshold(gray_img, threshold_value, 255, cv.THRESH_BINARY)\n",
    "    _, labels, stats, centroids = cv.connectedComponentsWithStats(binary_image)\n",
    "\n",
    "    num_labels = len(stats) - 1\n",
    "\n",
    "    for i in range(1, num_labels + 1):\n",
    "        x,y,w,h,_ = stats[i]\n",
    "        cv.rectangle(src_img, (x, y), (x+w, y+h), (0, 255, 0), 2)\n",
    "\n",
    "    return src_img\n",
    "\n",
    "white = {\n",
    "    \"org\": (10,30),\n",
    "    \"fontFace\": cv.FONT_HERSHEY_SIMPLEX,\n",
    "    \"fontScale\": 1,\n",
    "    \"thickness\": 2,\n",
    "    \"color\": (255,255,255),\n",
    "    \"lineType\": cv.LINE_AA\n",
    "}\n",
    "\n",
    "black = white.copy()\n",
    "black[\"color\"] = 0\n",
    "black[\"thickness\"] = 10\n",
    "\n",
    "\n",
    "image_txt = cv.putText(image.copy(), \"Original Image\", **black)\n",
    "image_txt = cv.putText(image_txt, \"Original Image\", **white)\n",
    "\n",
    "eroded_image_txt = cv.putText(eroded_image.copy(), f\"Eroded Image\", **black)\n",
    "eroded_image_txt = cv.putText(eroded_image_txt, f\"Eroded Image\", **white)\n",
    "\n",
    "cv.imshow(\"Eroded Image\", cv.vconcat([\n",
    "    cv.hconcat([image_txt, draw_connected_image(image.copy())]),\n",
    "    np.zeros((10, image.shape[1] * 2, 3), dtype=np.uint8) + 255,\n",
    "    cv.hconcat([eroded_image_txt, draw_connected_image(eroded_image.copy())])\n",
    "]))\n",
    "\n",
    "cv.waitKey(0)\n",
    "cv.destroyAllWindows()"
   ],
   "id": "9a005cf6be0a3a3f",
   "outputs": [],
   "execution_count": 8
  },
  {
   "metadata": {},
   "cell_type": "code",
   "outputs": [],
   "execution_count": null,
   "source": "",
   "id": "e212744510adcc2d"
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 3",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 2
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython2",
   "version": "2.7.6"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 5
}
